package result;

import idx.Extractor;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.PriorityQueue;
import java.util.Vector;

//import ruc.irm.similarity.word.hownet2.concept.LiuConceptParser;
//import ruc.irm.similarity.word.hownet2.concept.XiaConceptParser;

import main.Main;
//import ruc.irm.similarity.word.hownet2.concept.XiaConceptParser;
import datastructure.Candidateprc;
import datastructure.Querystruct;
import datastructure.sentence;
import datastructure.word;

//get an sentence and a bunch of documents, return the best sentence that matches the query.
public class ResultExtractor {
	static double Score[] = {1,1,0.9,0.9,0.75,0.75,0.65,0.65,0.45,0.45};
	String qtag = "";
	public PriorityQueue<Candidate> q2 = new PriorityQueue<Candidate>(50,new Comparator<Candidate>()
            {
		        public int compare(Candidate o1, Candidate o2)
		        {
		            return (int)(o2.score * 1000 - o1.score * 1000);
		        }
            }
    );
	public PriorityQueue<Candidate> q1 = new PriorityQueue<Candidate>(50,new Comparator<Candidate>()
            {
		        public int compare(Candidate o1, Candidate o2)
		        {
		            return (int)(o2.score * 1000 - o1.score * 1000);
		        }
            }
    );
	
	public PriorityQueue<Candidate> q3 = new PriorityQueue<Candidate>(50,new Comparator<Candidate>()
            {
		        public int compare(Candidate o1, Candidate o2)
		        {
		            return (int)(o2.score * 1000 - o1.score * 1000);
		        }
            }
    );

	public static void main(String [] args) throws IOException
	{
		//File[] doc = new File("/home/antony/Documents/wiki/zh/articles/多/瑙/河").listFiles();
		//ResultExtractor re = new ResultExtractor();
		String line = "<q>世界上现存最大的佛教艺术宝库是哪个？</q>";
		System.out.println(new String(line).substring(3, line.length() - 4));
	}
	class Candidate
	{
		String str;
		String title;
		double score;
		int pos;
		public Candidate(String a, double b, int c, String d)
		{
			str = a;
			score = b;
			pos = c;
			title = d;
		}
	}
	public String TopNSentence(Querystruct query, File [] doc, int n) throws IOException
	{
		qtag = query.qtag;
		int pos = 0;
		double max = 0;
		String stc = "";
		Extractor ex = new Extractor();
		ex.buildConvertTable("table.txt");
		for(int i = 0; i < doc.length; i++)
		{
			//System.out.println(doc[i].getName());
			String docName = ex.Convert(doc[i].getName());
			if(!docName.endsWith(".ext") || docName.startsWith("Talk") ||
			docName.startsWith("Category") || docName.startsWith("User"))
				continue;
			Vector<String> sentence = SplitDoc(doc[i]);
			if(sentence.elementAt(0).startsWith("Redirecting to"))
				continue;
			for(int j = 0; j < sentence.size(); j++)
			{
				String tempstc = sentence.elementAt(j);
				double sim = 0;
				//MUST contain VERY IMPORTANT WORD
				boolean containViword = true;
				//System.out.println(query.viword.size());
				for(int z = 0; z < query.viword.size(); z++)
				{
					String VIW = query.viword.get(z);
					//System.out.println(VIW + " " + VIW.length());
					//System.out.println(tempstc + " " + tempstc.indexOf(VIW));
					
					if(tempstc.indexOf(VIW) == -1)
					{
						containViword = false;
						break;
					}
				}
				if(containViword)
				{
					
					//System.out.println(tempstc);
					//System.out.println(query.keyword.size());
					
					
					sim = FeatureExtractor.ftrCal(query.sent, tempstc, docName);
					String title = docName.replaceAll(".html.ext", "");
					Candidate can = new Candidate(tempstc,sim,i,title);
					q2.offer(can);
					q1.offer(can);
					q3.offer(can);
					//System.out.println(sim);
				}
					
				//System.out.println(tempstc);
				
				if(sim > max)
				{
					max = sim;
					pos = i;
					stc = tempstc;
				}
			}
		}
		if(max == 0)
			return "NIL";
		String result = "";
		
		/*for(int i = 0; i < n; i++)
		{
			Candidate tempcan = q3.poll();
			if(tempcan == null)
				break;
			System.out.println(tempcan.str + ":" + tempcan.score + "--" + doc[tempcan.pos].getName());
		}
		*/
		/*
		for(int i = 0; i < n; i++)
		{
			Candidate tempcan = q3.poll();
			if(tempcan == null)
				break;
			if(!(result = getExact(query, tempcan.str)).equals(""))
			{
				return tempcan.str + "--" + doc[tempcan.pos].getName() + "--" + result;
			}
		}
		
		for(int i = 0; i < n; i++)
		{
			Candidate tempcan = q1.poll();
			if(tempcan == null)
				break;
			if(!(result = getObscure(query, tempcan.str)).equals(""))
			{
				return tempcan.str + "--" + doc[tempcan.pos].getName() + "\n" + result;
			}
		}*/
		
		result = getResult(q2,n,query.require_pos,query);

		//return stc + "--" + doc[pos].getName() + "\n" + getExact(query, stc);
		if(result.equals(""))
			result = "NIL";
		return result;
	}
	
	public class grade
	{
		double score;
		double avgpos;
		int count;
		String pos;
		Hashtable<Integer,Integer> docnum;
		public grade(double a, double b,String c)
		{
			score = a;
			avgpos = b;
			count = 1;
			pos = c;
			docnum = new Hashtable<Integer,Integer>();
		}
	}
	
	public String getResult(PriorityQueue<Candidate> p, int n, String pos, Querystruct query)
	{
		//LiuConceptParser xp = LiuConceptParser.getInstance();
		Hashtable<String,grade> store = new Hashtable<String,grade>();
		ArrayList<String> selsen = new ArrayList<String>();
		int countsen = 0;
		int i = 0;
		while(i < n)
		{
			Candidate temp = p.poll();
			if(temp == null)
				break;
			countsen ++;
			int sennum = 0;
			boolean ishit = false;
			if((sennum = selsen.size()) > 0)
			{
				for(int k = 0; k < sennum; k++)
				{
					if(FeatureExtractor.EditDistance(temp.str, selsen.get(k)) < 3)
					{
						ishit = true;
						break;
					}
				}
			}
			if(ishit)
				continue;
			selsen.add(temp.str);
			Candidateprc can = new Candidateprc(temp.str,false);
			//System.out.println(temp.str);
			Candidateprc can1 = new Candidateprc(temp.title,false);
			System.out.println(temp.str + "---" + temp.title);
			int num = can.keyword.size();
			for(int j = 0; j < num; j++)
			{
				word wd = can.keyword.get(j);
				if(wd.pos.startsWith(pos)|| ((wd.pos.startsWith("x") ||wd.pos.equals("vip")) && pos.equals("n")))
				{
					String str = wd.content;
					if(store.containsKey(str))
					{
						grade d = store.get(str);
						if(d.docnum.containsKey(i))
						{
							int Num = d.docnum.get(i);
							Num++;
							d.docnum.remove(i);
							d.docnum.put(i, Num);
						}
						else
						{
							d.docnum.put(i, 1);
						}
						d.score += (temp.score/d.docnum.get(i));
						double sum = d.avgpos * (double)d.count;
						d.count ++;
						d.avgpos = (sum + i)/d.count;
						store.remove(str);
						store.put(str, d);
					}
					else
					{
						grade d = new grade(temp.score, (double)i, wd.pos);
						d.docnum.put(i, 1);
						store.put(str, d);
					}
				}
			}
			if(pos.equals("n"))
			{
				num = can.viword.size();
				for(int j = 0; j < num; j++)
				{
					word wd1 = can.viword.get(j);
					String str = wd1.content;
					if(store.containsKey(str))
					{
						grade d = store.get(str);
						if(d.docnum.containsKey(i))
						{
							int Num = d.docnum.get(i);
							Num++;
							d.docnum.remove(i);
							d.docnum.put(i, Num);
						}
						else
						{
							d.docnum.put(i, 1);
						}
						d.score += (temp.score/d.docnum.get(i));
						double sum = d.avgpos * (double)d.count;
						d.count ++;
						d.avgpos = (sum + i)/d.count;
						store.remove(str);
						store.put(str, d);
					}
					else
					{
						grade d = new grade(temp.score, (double)i, wd1.pos);
						d.docnum.put(i, 1);
						store.put(str, d);
					}
				}
			}
			num = can1.keyword.size();
			for(int j = 0; j < num; j++)
			{
				word wd = can1.keyword.get(j);
				if(wd.pos.startsWith(pos)|| ((wd.pos.startsWith("x") ||wd.pos.equals("vip")) && pos.equals("n")))
				{
					String str = wd.content;
					if(store.containsKey(str))
					{
						grade d = store.get(str);
						if(d.docnum.containsKey(i))
						{
							int Num = d.docnum.get(i);
							Num++;
							d.docnum.remove(i);
							d.docnum.put(i, Num);
						}
						else
						{
							d.docnum.put(i, 1);
						}
						d.score += (temp.score/d.docnum.get(i));
						double sum = d.avgpos * (double)d.count;
						d.count ++;
						d.avgpos = (sum + i)/d.count;
						store.remove(str);
						store.put(str, d);
					}
					else
					{
						grade d = new grade(temp.score, (double)i, wd.pos);
						d.docnum.put(i, 1);
						store.put(str, d);
					}
				}
			}
			if(pos.equals("n"))
			{
				num = can1.viword.size();
				for(int j = 0; j < num; j++)
				{
					word wd1 = can1.viword.get(j);
					String str = wd1.content;
					if(store.containsKey(str))
					{
						grade d = store.get(str);
						if(d.docnum.containsKey(i))
						{
							int Num = d.docnum.get(i);
							Num++;
							d.docnum.remove(i);
							d.docnum.put(i, Num);
						}
						else
						{
							d.docnum.put(i, 1);
						}
						d.score += (temp.score/d.docnum.get(i));
						double sum = d.avgpos * (double)d.count;
						d.count ++;
						d.avgpos = (sum + i)/d.count;
						store.remove(str);
						store.put(str, d);
					}
					else
					{
						grade d = new grade(temp.score, (double)i, wd1.pos);
						d.docnum.put(i, 1);
						store.put(str, d);
					}
				}
			}
			i++;
		}
		Enumeration e = store.keys();
		String result = "";
		double max = -1.0;
		double minpos = 100;
		//for(int i = 0; i < query.keyword.size(); i++)
			//System.out.println(query.keyword.get(i).content);
		while (e.hasMoreElements()) { 
			String key = (String) e.nextElement();
			//System.out.println(key);
			grade g = store.get(key);
			//System.out.println(g.score);
			if((g.score>max ||(g.score == max && g.avgpos < minpos)) 
					&& !query.content.contains(key)
					&& (!isremove(g,key,query)))
			{
				result = key;
				max = store.get(key).score;
				minpos = store.get(key).avgpos;
				System.out.println(result + " "+ max);
			}
		}
		if(countsen >=7 && max < 1 && pos.equals("n"))
			result = "";
		if(countsen >=7 && max < 0.4 && !pos.equals("n"))
			result = "";
		return result;
	}
	
	boolean isremove(grade g, String str, Querystruct query)
	{
		String num[] = {"1","0","2","3","4","5","6","7","8","9","零","一","二","三","四",
				"五","六","七","八","九","十"};
		String a[] = {"_","晚期","今","中华人民共和国","金球","Wikipedia","Portal","後来"};
		for(int i = 0; i < a.length; i++)
		{
			if(a[i].equals(str))
				return true;
		}
		if(g.pos.startsWith("ng") && Main.stopword.containsKey(str))
			return true;
		if(g.pos.equals("n") && str.length() <= 1)
			return true;
		if(g.pos.equals("n") && Main.stopword.containsKey(str))
		{
			return true;
		}
		boolean find = false;
		if(g.pos.startsWith("m"))
		{
			for(int i = 0; i < num.length; i++)
			{
				if(str.indexOf(num[i])!=-1)
				{
					find = true;
				}
			}
			if(!find)
				return true;
		}
		if(g.pos.startsWith("t"))
		{
			for(int i = 0; i < num.length; i++)
			{
				if(str.indexOf(num[i])!=-1)
				{
					find = true;
				}
			}
			if(!find && Main.stopword.containsKey(str))
				return true;
		}
		if(qtag.equals("哪一年")||qtag.equals("哪年"))
		{
			if(!str.endsWith("年"))
			{
				return true;
			}
		}
		if(qtag.equals("哪一月")||qtag.equals("哪月"))
		{
			if(!str.endsWith("月"))
			{
				return true;
			}
		}
		if(qtag.equals("哪一天")||qtag.equals("哪天"))
		{
			if(!str.endsWith("日"))
			{
				return true;
			}
		}
		if(qtag.equals("多少") || qtag.equals("几"))
		{
			if(str.endsWith("年"))
			{
				return true;
			}
		}
		if(str.endsWith("省") && query.content.contains(str.replace("省", "")))
			return true;
		if(str.endsWith("市") && query.content.contains(str.replace("市", "")))
			return true;
		if(str.endsWith("县") && query.content.contains(str.replace("县", "")))
			return true;
		return false;
	}
	
	public String getExact(Querystruct query, String stc) throws IOException
	{
		//System.out.println(stc);
		String [] phrs = stc.split("，");
		int pos = 0;
		double max = 0;
		//System.out.println(query.require_pos);
		for(int i = 0 ; i < phrs.length; i++)
		{
			double tempsim = FeatureExtractor.wordSim(query.sent, phrs[i], null);
			if(tempsim > max)
			{
				max = tempsim;
				pos = i;
			}
		}
		//get the best phrase, then extract the words
		boolean find = false;
		int offset = 0;
		String result = "";
		while(find == false)
		{
			if(pos + offset >= phrs.length && pos - offset < 0)
				break;
			if(pos + offset < phrs.length)
			{
				sentence getWord = new sentence(phrs[pos + offset]);
				for(int i = 0; i < getWord.keyword.size(); i++)
				{
					if(getWord.keyword.get(i).pos.startsWith(query.require_pos))
					{
						if(!query.content.contains(getWord.keyword.get(i).content))
						{
							result = getWord.keyword.get(i).content;
							find = true;
							break;
						}
					}
				}
			}
			if(pos - offset >= 0)
			{
				sentence getWord = new sentence(phrs[pos - offset]);
				for(int i = 0; i < getWord.keyword.size(); i++)
				{
					if(getWord.keyword.get(i).pos.startsWith(query.require_pos))
					{
						if(!query.content.contains(getWord.keyword.get(i).content))
						{
							result = getWord.keyword.get(i).content;
							find = true;
							break;
						}
					}
				}
			}
			offset ++;
		}
		return result;
	}

	public String getObscure(Querystruct query, String stc) throws IOException
	{
		//System.out.println(stc);
		String [] phrs = stc.split("，");
		int pos = 0;
		double max = 0;
		//System.out.println(query.require_pos);
		for(int i = 0 ; i < phrs.length; i++)
		{
			double tempsim = FeatureExtractor.wordSim(query.sent, phrs[i], null);
			if(tempsim > max)
			{
				max = tempsim;
				pos = i;
			}
		}
		//get the best phrase, then extract the words
		boolean find = false;
		int offset = 0;
		String result = "";
		while(find == false)
		{
			if(pos + offset >= phrs.length && pos - offset < 0)
				break;
			if(pos + offset < phrs.length)
			{
				sentence getWord = new sentence(phrs[pos + offset]);
				for(int i = 0; i < getWord.keyword.size(); i++)
				{
					if(getWord.keyword.get(i).pos.startsWith("n"))
					{
						if(!query.content.contains(getWord.keyword.get(i).content))
						{
							result = getWord.keyword.get(i).content;
							find = true;
							break;
						}
					}
				}
			}
			if(pos - offset >= 0)
			{
				sentence getWord = new sentence(phrs[pos - offset]);
				for(int i = 0; i < getWord.keyword.size(); i++)
				{
					if(getWord.keyword.get(i).pos.startsWith("n"))
					{
						if(!query.content.contains(getWord.keyword.get(i).content))
						{
							result = getWord.keyword.get(i).content;
							find = true;
							break;
						}
					}
				}
			}
			offset ++;
		}
		return result;
	}
	
	
	public Vector<String> SplitDoc(File doc) throws IOException
	{
		BufferedReader reader = new BufferedReader(new FileReader(doc));
		String line = "";
		Vector<String> sentence = new Vector<String>();
		while ((line = reader.readLine()) != null)
		{
			String [] temp = line.split("。");
			for(int i = 0; i < temp.length; i++)
				sentence.add(temp[i]);
		}
		reader.close();
		return sentence;
	}
}
